/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package easyanimation.panel.left;

import easyanimation.frame.CConfig;
import easyanimation.frame.Constant;
import easyanimation.frame.Language;
import easyanimation.frame.MainWindow;
import javax.swing.JOptionPane;
import javax.swing.table.AbstractTableModel;

/**
 *
 * @author Ngoc Tan
 */
public class CTableModel extends AbstractTableModel
{
    //------------------------Variables
    //default variables
    private String[] m_columnNamesStrings =
    {
    };
    private Object[][] m_dataObjectses =
    {
    };
    //more
    private int[] m_columnsNonEditableIs =
    {
    };
    //more
    private int[] m_columnsIntegerIs =
    {
    };
    private int[] m_columnsIntegerPositiveIs =
    {
    };
    private boolean m_isSubTable = false;
    private Object m_oldDataObject;
    //--------------------------Methods

    public CTableModel(int iArrColumnsNonEditable[],
            int iArrColumnsInteger[],
            int iArrColumnsIntegerPositive[],
            boolean bIsSubTable)
    {
        m_columnsNonEditableIs = iArrColumnsNonEditable;
        m_columnsIntegerIs = iArrColumnsInteger;
        m_columnsIntegerPositiveIs = iArrColumnsIntegerPositive;
        m_isSubTable = bIsSubTable;
    }

    @Override
    public int getColumnCount()
    {
        return m_columnNamesStrings.length;
    }

    @Override
    public int getRowCount()
    {
        return m_dataObjectses.length;
    }

    @Override
    public String getColumnName(int col)
    {
        return m_columnNamesStrings[col];
    }

    @Override
    public Object getValueAt(int row, int col)
    {
        if (m_dataObjectses.length < 0)
        {
            return null;
        }
        return m_dataObjectses[row][col];
    }

    @Override
    /*
     * JTable uses this method to determine the default renderer/
     * editor for each cell.  If we didn't implement this method,
     * then the last column would contain text ("true"/"false"),
     * rather than a check box.
     */
    public Class getColumnClass(int c)
    {
        return getValueAt(0, c).getClass();
    }

    @Override
    /*
     * Don't need to implement this method unless your table's
     * editable.
     */
    public boolean isCellEditable(int row, int col)
    {
        //Note that the data/cell address is constant,
        //no matter where the cell appears onscreen.
        for (int i = 0; i < m_columnsNonEditableIs.length; i++)
        {
            if (col == m_columnsNonEditableIs[i])
            {
                return false;
            }
        }
        return true;

    }

    @Override
    /*
     * Don't need to implement this method unless your table's
     * data can change.
     */
    public void setValueAt(Object value, int row, int col)
    {
        if (m_dataObjectses.length < 0)
        {
            return;
        }
        m_dataObjectses[row][col] = value;
        fireTableCellUpdated(row, col);
    }

    /**
     * set new column name
     * @param a 
     */
    public void setColumnNames(String a[])
    {
        m_columnNamesStrings = a;
    }

    /**
     * Set new data
     * @param a 
     */
    public void setData(Object a[][])
    {
        m_dataObjectses = a;
    }

    /**
     * Add new row
     */
    public int addRow(Object[] dataObjects)
    {
        int rows = m_dataObjectses.length;
        int columns = m_columnNamesStrings.length;
        Object[][] tempDataObjectses = new Object[rows + 1][columns];
        //array copy
        for (int i = 0; i < rows; i++)
        {
            System.arraycopy(m_dataObjectses[i], 0, tempDataObjectses[i], 0, columns);
        }
        //add new row
        tempDataObjectses[rows] = dataObjects.clone();
        tempDataObjectses[rows][0] = (rows == 0) ? 0 : ((Integer) m_dataObjectses[rows - 1][0] + 1);
        //update data        
        m_dataObjectses = tempDataObjectses;
        return rows;
    }

    /**
     * insert new row
     */
    public int insertRow(int rowInsert, Object[] data)
    {
        int rows = m_dataObjectses.length;
        //if no row selected
        if (rowInsert == -1 || rowInsert >= rows)
        {
            return addRow(data);
        }
        int columns = m_columnNamesStrings.length;
        Object[][] tempData = new Object[rows + 1][columns];
        //array copy
        for (int i = 0; i <= rowInsert; i++)
        {
            //copy
            System.arraycopy(m_dataObjectses[i], 0, tempData[i], 0, columns);
        }
        //insert new row
        tempData[rowInsert + 1] = data.clone();
        tempData[rowInsert + 1][0] = rowInsert + 1; //change the id
        //copy remain array
        for (int i = rowInsert + 1; i < rows; i++)
        {
            //copy
            System.arraycopy(m_dataObjectses[i], 0, tempData[i + 1], 0, columns);
            //shift id
            tempData[i + 1][0] = (Integer) tempData[i + 1][0] + 1;
        }
        //update data
        m_dataObjectses = tempData;
        return rowInsert + 1;
    }

    /**
     * Delete a row
     */
    public void deleteRow(int rowDel)
    {
        int rows = m_dataObjectses.length;
        //if rowDel out of range
        if (rowDel >= rows)
        {
            return;
        }

        int columns = m_columnNamesStrings.length;
        Object[][] tempData = new Object[rows - 1][columns];
        //array copy
        for (int i = 0; i < rowDel; i++)
        {
            System.arraycopy(m_dataObjectses[i], 0, tempData[i], 0, columns);
        }
        for (int i = rowDel + 1; i < rows; i++)
        {
            //copy
            System.arraycopy(m_dataObjectses[i], 0, tempData[i - 1], 0, columns);
            //shift id
            tempData[i - 1][0] = (Integer) tempData[i - 1][0] - 1;
        }
        //update data
        m_dataObjectses = tempData;
    }

    @Override
    public void fireTableCellUpdated(int row, int column)
    {
        super.fireTableCellUpdated(row, column);
        String strValue = (String) m_dataObjectses[row][column];
        boolean bIsChecked = false;
        if (m_columnsIntegerIs != null)
        {
            for (int i = 0; i < m_columnsIntegerIs.length; i++)
            {
                if (column == m_columnsIntegerIs[i])
                {
                    if (!strValue.matches("(\\+|-)?\\d+")) // check whether string contains numeric chacracters, "-" or not
                    {
                        JOptionPane.showMessageDialog(MainWindow.getInstance(),
                                Language.MESSAGE_WRONG_NUMERIC[CConfig.LANGUAGE],
                                Language.ERROR[CConfig.LANGUAGE],
                                JOptionPane.ERROR_MESSAGE);
                        m_dataObjectses[row][column] = m_oldDataObject;
                        return;
                    }
                    else //if true
                    {
                        try
                        {
                            m_dataObjectses[row][column] = new Integer(Integer.parseInt(strValue)).toString(); //remove 0 in front of the number
                            bIsChecked = true;
                        } catch (NumberFormatException numberFormatException)
                        {
                            JOptionPane.showMessageDialog(MainWindow.getInstance(),
                                    Language.MESSAGE_TOO_LARGE_NUMBER[CConfig.LANGUAGE], Language.ERROR[CConfig.LANGUAGE],
                                    JOptionPane.ERROR_MESSAGE);
                            m_dataObjectses[row][column] = m_oldDataObject;
                            return;
                        }
                    }
                    break;
                }
            }
        }
        if (m_columnsIntegerPositiveIs != null)
        {
            for (int i = 0; i < m_columnsIntegerPositiveIs.length; i++)
            {
                if (column == m_columnsIntegerPositiveIs[i])
                {
                    if (!strValue.matches("\\d+")) // check whether string contains numeric chacracters or not
                    {
                        JOptionPane.showMessageDialog(MainWindow.getInstance(),
                                Language.MESSAGE_WRONG_NUMERIC_POSITIVE[CConfig.LANGUAGE],
                                Language.ERROR[CConfig.LANGUAGE],
                                JOptionPane.ERROR_MESSAGE);
                        //m_objArrData[row][column] = m_objOldData;                        
                        m_dataObjectses[row][column] = "0";
                        //MainWindow.getInstance().getCenterPanel().updateAfterModifiedTable(m_bIsSubTable);
                        MainWindow.getInstance().getCenterPanel().updateFromTable(m_isSubTable, Constant.TABLE_ACTION_UPDATE, row, null);
                        //getCenterPanel().updateAfterModifiedTable(m_bIsSubTable);
                        return;
                    }
                    else //if true
                    {
                        try
                        {
                            m_dataObjectses[row][column] = new Integer(Integer.parseInt(strValue)).toString(); //remove 0 in front of the number
                            bIsChecked = true;
                        } catch (NumberFormatException numberFormatException)
                        {
                            JOptionPane.showMessageDialog(MainWindow.getInstance(),
                                    Language.MESSAGE_TOO_LARGE_NUMBER[CConfig.LANGUAGE],
                                    Language.ERROR[CConfig.LANGUAGE],
                                    JOptionPane.ERROR_MESSAGE);
                            m_dataObjectses[row][column] = m_oldDataObject;
                            return;
                        }
                    }
                    break;
                }
            }
        }
        if (!bIsChecked && !strValue.matches("\\w+")) // check whether string contains word chacracters or not
        {
            JOptionPane.showMessageDialog(MainWindow.getInstance(),
                    Language.MESSAGE_WRONG_CHARACTER[CConfig.LANGUAGE],
                    Language.ERROR[CConfig.LANGUAGE],
                    JOptionPane.ERROR_MESSAGE);
            m_dataObjectses[row][column] = m_oldDataObject;
            return;
        }
    }

    public void storeOldState(int row, int column)
    {
        if (m_dataObjectses.length < 1)
        {
            return;
        }
        if (row < 0 || column < 0)
        {
            m_oldDataObject = null;
        }
        else
        {
            m_oldDataObject = m_dataObjectses[row][column];
        }
    }

    /**
     * @return the m_objOldData
     */
    public Object getOldData()
    {
        return m_oldDataObject;
    }

    public void removeAllRow()
    {
        m_dataObjectses = new Object[][]
        {
        };
        System.gc();
    }
}

